home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / VMSTTY.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  7KB  |  252 lines

  1. /*    SCCS Id: @(#)vmstty.c    3.0    88/05/03
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4. /* tty.c - (VMS) version */
  5.  
  6. #define NEED_VARARGS
  7. #include "hack.h"
  8.  
  9. #include    <descrip.h>
  10. #include    <iodef.h>
  11. #include    <smgdef.h>
  12. #include    <ttdef.h>
  13. #include <errno.h>
  14.  
  15. #define vms_ok(sts) ((sts)&1)
  16. #define META(c)  ((c)|0x80)    /*(Same as DOS's M(c).)*/
  17. #define CTRL(c)  ((c)&0x1F)
  18. #define CMASK(c) (1<<CTRL(c))
  19. #define LIB$M_CLI_CTRLT CMASK('T')    /* 0x00100000 */
  20. #define LIB$M_CLI_CTRLY CMASK('Y')    /* 0x02000000 */
  21.  
  22. extern short ospeed;
  23. char erase_char, intr_char, kill_char;
  24. static boolean settty_needed = FALSE,  bombing = FALSE;
  25. #ifndef MAIL
  26. static        /* else global ('extern' in mail.c) */
  27. #endif
  28.        unsigned long pasteboard_id = 0; /* for AST & broadcast-msg handling */
  29. static unsigned long kb = 0;
  30.  
  31. int
  32. vms_getchar()
  33. {
  34.     static volatile int recurse = 0;    /* SMG is not AST re-entrant! */
  35.     short key;
  36.  
  37.     if (recurse++ == 0 && kb != 0) {
  38.     SMG$READ_KEYSTROKE(&kb, &key);
  39.     switch (key)
  40.     {
  41.       case SMG$K_TRM_UP:
  42.         key = 'k';
  43.         break;
  44.       case SMG$K_TRM_DOWN:
  45.         key = 'j';
  46.         break;
  47.       case SMG$K_TRM_LEFT:
  48.         key = 'h';
  49.         break;
  50.       case SMG$K_TRM_RIGHT:
  51.         key = 'l';
  52.         break;
  53.       case '\r':
  54.         key = '\n';
  55.         break;
  56.       default:
  57.         if (key == '\007' || key == '\032' || key > 255)
  58.         key = '\033';
  59.         break;
  60.     }
  61.     } else {
  62.     /* abnormal input--either SMG didn't initialize properly or
  63.        vms_getchar() has been called recursively (via SIGINT handler).
  64.      */
  65.     if (kb != 0)            /* must have been a recursive call */
  66.         SMG$CANCEL_INPUT(&kb);    /*  from an interrupt handler       */
  67.     key = getchar();
  68.     }
  69.     --recurse;
  70.     return (int)key;
  71. }
  72.  
  73. #define TT_SPECIAL_HANDLING (TT$M_MECHTAB|TT$M_MECHFORM)
  74. #define Uword unsigned short
  75. #define Ubyte unsigned char
  76. struct _sm_iosb {        /* i/o status block for sense-mode qio */
  77.     Uword      status;
  78.     Ubyte      xmt_speed,  rcv_speed;
  79.     Ubyte      cr_fill,  lf_fill,  parity;
  80.     unsigned   : 8;
  81. };
  82. struct _sm_bufr {        /* sense-mode characteristics buffer */
  83.     Ubyte      class,  type;        /* class==DC$_TERM, type==(various) */
  84.     Uword      buf_siz;        /* aka page width */
  85. #define page_width buf_siz        /* number of columns */
  86.     unsigned  tt_char  : 24;    /* primary characteristics */
  87.     Ubyte      page_length;        /* number of lines */
  88.     unsigned  tt2_char : 32;    /* secondary characteristics */
  89. };
  90. static struct {
  91.     struct _sm_iosb io;
  92.     struct _sm_bufr sm;
  93. } sg = {{0},{0}};
  94. static unsigned short tt_chan = 0;
  95. static unsigned long  tt_char_restore = 0, tt_char_active = 0;
  96. static unsigned long  ctrl_mask = 0;
  97.  
  98. static void
  99. setctty(){
  100.     struct _sm_iosb iosb;
  101.     long status = SYS$QIOW(0, tt_chan, IO$_SETMODE, &iosb, (void(*)())0, 0,
  102.                &sg.sm, sizeof sg.sm, 0, 0, 0, 0);
  103.     if (vms_ok(status))  status = iosb.status;
  104.     if (!vms_ok(status)) {
  105.     errno = EVMSERR,  vaxc$errno = status;
  106.     perror("NetHack (setctty: setmode)");
  107.     }
  108. }
  109.  
  110. static void
  111. resettty(){            /* atexit() routine */
  112.     if (settty_needed) {
  113.     bombing = TRUE;     /* don't clear screen; preserve traceback info */
  114.     settty((char *)NULL);
  115.     }
  116.     (void) SYS$DASSGN(tt_chan),  tt_chan = 0;
  117. }
  118.  
  119. /*
  120.  * Get initial state of terminal, set ospeed (for termcap routines)
  121.  * and switch off tab expansion if necessary.
  122.  * Called by startup() in termcap.c and after returning from ! or ^Z
  123.  */
  124. void
  125. gettty(){
  126.     long status;
  127.     $DESCRIPTOR(input_dsc, "TT");
  128.     unsigned long zero = 0;
  129.  
  130.     if (tt_chan == 0) {        /* do this stuff once only */
  131.     status = SYS$ASSIGN(&input_dsc, &tt_chan, 0, 0);
  132.     if (!vms_ok(status)) {
  133.         errno = EVMSERR,  vaxc$errno = status;
  134.         perror("NetHack (gettty: $assign)");
  135.     }
  136.     atexit(resettty);   /* register an exit handler to reset things */
  137.     }
  138.     status = SYS$QIOW(0, tt_chan, IO$_SENSEMODE, &sg.io, (void(*)())0, 0,
  139.               &sg.sm, sizeof sg.sm, 0, 0, 0, 0);
  140.     if (vms_ok(status))  status = sg.io.status;
  141.     if (!vms_ok(status)) {
  142.     errno = EVMSERR,  vaxc$errno = status;
  143.     perror("NetHack (gettty: sensemode)");
  144.     }
  145.     ospeed = sg.io.xmt_speed;
  146.     erase_char = '\177';    /* <rubout>, aka <delete> */
  147.     kill_char = CTRL('U');
  148.     intr_char = CTRL('C');
  149.     (void) LIB$ENABLE_CTRL(&zero, &ctrl_mask);
  150.     /* Use the systems's values for lines and columns if it has any idea. */
  151.     if (sg.sm.page_length)
  152.     LI = sg.sm.page_length;
  153.     if (sg.sm.page_width)
  154.     CO = sg.sm.page_width;
  155.     /* Determine whether TTDRIVER is doing tab and/or form-feed expansion;
  156.        if so, we want to suppress that but also restore it at final exit. */
  157.     if ((sg.sm.tt_char & TT_SPECIAL_HANDLING) != TT_SPECIAL_HANDLING) {
  158.     tt_char_restore = sg.sm.tt_char;
  159.     tt_char_active    = sg.sm.tt_char |= TT_SPECIAL_HANDLING;
  160. #if 0        /*[ defer until setftty() ]*/
  161.     setctty();
  162. #endif 0
  163.     } else    /* no need to take any action */
  164.     tt_char_restore = tt_char_active = 0;
  165. }
  166.  
  167. /* reset terminal to original state */
  168. void
  169. settty(s)
  170. char *s;
  171. {
  172.     if (!bombing) {
  173.         end_screen();
  174.         if(s) Printf(s);
  175.         (void) fflush(stdout);
  176.     }
  177. #ifdef MAIL    /* this is essential, or lib$spawn & lib$attach will fail */
  178.     SMG$DISABLE_BROADCAST_TRAPPING(&pasteboard_id);
  179. #endif
  180. #if 0        /* let SMG's exit handler do the cleanup (as per doc) */
  181.     SMG$DELETE_PASTEBOARD(&pasteboard_id);
  182.     SMG$DELETE_VIRTUAL_KEYBOARD(&kb),  kb = 0;
  183. #endif 0
  184.     if (ctrl_mask)
  185.         (void) LIB$ENABLE_CTRL(&ctrl_mask, 0);
  186.     flags.echo = ON;
  187.     flags.cbreak = OFF;
  188.     if (tt_char_restore != 0) {
  189.         sg.sm.tt_char = tt_char_restore;
  190.         setctty();
  191.     }
  192.     settty_needed = FALSE;
  193. }
  194.  
  195. #ifdef MAIL
  196. static void
  197. broadcast_ast(dummy)
  198. {
  199.     extern volatile int broadcasts;
  200.  
  201.     broadcasts++;
  202. }
  203. #endif
  204.  
  205. void
  206. setftty(){
  207.     unsigned int mask = LIB$M_CLI_CTRLT | LIB$M_CLI_CTRLY;
  208.  
  209.     flags.cbreak = ON;
  210.     flags.echo = OFF;
  211.     (void) LIB$DISABLE_CTRL(&mask, 0);
  212.     if (kb == 0) {        /* do this stuff once only */
  213.     SMG$CREATE_VIRTUAL_KEYBOARD(&kb);
  214.     SMG$CREATE_PASTEBOARD(&pasteboard_id, 0, 0, 0, 0);
  215.     }
  216. #ifdef MAIL
  217.     /* note side effect: also intercepts hangup notification */
  218.     SMG$SET_BROADCAST_TRAPPING(&pasteboard_id, broadcast_ast, 0);
  219. #endif
  220.     /* disable tab & form-feed expansion */
  221.     if (tt_char_active != 0) {
  222.         sg.sm.tt_char = tt_char_active;
  223.         setctty();
  224.     }
  225.     start_screen();
  226.     settty_needed = TRUE;
  227. }
  228.  
  229.  
  230. void
  231. intron() {        /* enable kbd interupts if enabled when game started */
  232. }
  233.  
  234. void
  235. introff() {        /* disable kbd interrupts if required*/
  236. }
  237.  
  238.  
  239. /* fatal error */
  240. /*VARARGS1*/
  241. void
  242. error VA_DECL(const char *,s)
  243.     VA_START(s);
  244.     VA_INIT(s, const char *);
  245.     if(settty_needed)
  246.         settty(NULL);
  247.     Vprintf(s,VA_ARGS);
  248.     (void) putchar('\n');
  249.     VA_END();
  250.     exit(1);
  251. }
  252.